﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Task_Parallel_Library
{
    [TestClass]
    public class Plinq
    {
        [TestMethod]
        public void SimpleExample()
        {
            //initialize
            var count = 10000;
            var source = Enumerable.Range(1, count);

            //execute
            var evenNums = source.AsParallel().Where(num => num % 2 == 0).ToList();

            //assert
            Assert.AreEqual(count / 2, evenNums.Count);
        }

        [TestMethod]
        public void UsingOnly3Tasks()
        {
            //initialize
            var count = 10000;
            var source = Enumerable.Range(1, count);

            //execute
            var evenNums = source.AsParallel().WithDegreeOfParallelism(3).Where(num => num % 2 == 0).ToList();

            //assert
            Assert.AreEqual(count / 2, evenNums.Count);
        }

        [TestMethod]
        public void KeepingOrder()
        {
            //initialize
            var count = 10000;
            var source = Enumerable.Range(1, count);

            //execute
            Func<int, bool> predicate = num => num % 2 == 0;
            var evenNums = source.AsParallel().AsOrdered().Where(predicate).ToList();

            //assert
            CollectionAssert.AreEqual(source.Where(predicate).ToList(), evenNums);
        }

        [TestMethod]
        public void ConvertingToSecuenecialAfterSomePoint()
        {
            //initialize
            var count = 10000;
            var source = Enumerable.Range(1, count);

            //execute
            Func<int, bool> predicate = num => num % 2 == 0;
            var evenNums = source.AsParallel().AsOrdered().Where(predicate).AsSequential().Take(2).ToList();

            //assert
            CollectionAssert.AreEqual(source.Where(predicate).Take(2).ToList(), evenNums);
        }

        [TestMethod]
        public void WithMergeOptions()
        {
            //initialize
            var count = 10000;
            var source = Enumerable.Range(1, count);

            //execute
            Func<int, bool> predicate = num => num % 2 == 0;
            var evenNums = source.AsParallel().AsOrdered().Where(predicate).WithMergeOptions(ParallelMergeOptions.NotBuffered).ToList();

            //assert
            CollectionAssert.AreEqual(source.Where(predicate).ToList(), evenNums);
        }

        [TestMethod]
        public void TestMethod()
        {
            //initialize
            var nums = Enumerable.Range(10, 10000);
            var concurrentBag = new ConcurrentBag<int>();

            //execute
            var query = nums.AsParallel().Where(num => num % 10 == 0);
            // Process the results as each thread completes 
            query.ForAll(concurrentBag.Add);

            //assert
            Assert.IsTrue(concurrentBag.Count > 0);
        }       
    }
}
